package org.stars.dao.loader;

import java.io.File;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.stars.config.AppSettings;
import org.stars.config.Message;
import org.stars.dao.config.Source;
import org.stars.dao.config.Sources;
import org.stars.dao.sqlmapper.SqlMapper;
import org.stars.dao.sqlmapper.parser.TemplateParser;
import org.stars.dao.sqlmapper.parser.TemplateParser2;
import org.stars.datastructure.map.CaseInsensitiveHashMap;
import org.stars.util.FileResourceUtility;
import org.stars.util.FileUtility;
import org.stars.util.StringUtility;
import org.stars.util.jar.JarResourceUtility;

import static org.stars.config.Message.SOURCE_LOADER_01;
import static org.stars.config.Message.SOURCE_LOADER_02;
import static org.stars.config.Message.SOURCE_LOADER_03;

public abstract class SourceLoader {
	protected static Log log = LogFactory.getLog(SourceLoader.class);
	protected String jarName;

	protected static Map<String, SqlMapper> loadFromDefinition(Sources sources)
			throws Exception {
		Map<String, SqlMapper> mapper = new CaseInsensitiveHashMap<SqlMapper>();
		SourceFinder rh = new SourceFinder();
		String path;

		for (Source item : sources.getList()) {
			// clear status of resourceHandler
			rh.clear();
			if (!item.isJarResource()) {
				// ASSERT: siamo su file system
				rh.setJarName(null);
				path = item.getDirectory();

				path = StringUtility.replace(
						path,
						"${" + XmlConfigLoader.DAOSTARS_CONFIG_DIR + "}",
						AppSettings
								.getInstance()
								.getParameter(
										XmlConfigLoader.DAOSTARS_CONFIG_DIR)
								.toString());
				path = FileUtility.adjustPath(path);

				item.setDirectory(path);

				FileResourceUtility.findResources(path, item.getFilePattern(),
						rh);
			} else {
				rh.setJarName(item.getJar());
				JarResourceUtility.findResources(item.getJar(),
						item.getDirectory(), item.getFilePattern(), rh);
			}

			int i = 0;
			SqlMapper old = null;
			// put every sqlMapper found in result
			for (SqlMapper item2 : rh.getSqlMappers()) {

				old = mapper.get(item2.getId());
				if (old != null) {
					log.warn(Message.SOURCE_LOADER_04.with(item2.getId(),
							item2.getSource(), old.getSource()));
				}
				mapper.put(item2.getId(), item2);
				i++;
			}

			if (item.isJarResource()) {
				log.debug(SOURCE_LOADER_01.with(mapper.size(), item.getJar(),
						item.getDirectory(), item.getFilePattern()));
			} else {

				log.debug(SOURCE_LOADER_02.with(mapper.size(),
						(new File(item.getDirectory())).getAbsoluteFile(),
						item.getFilePattern()));
			}
		}

		log.debug(SOURCE_LOADER_03.with(mapper.size()));

		return mapper;
	}

	/**
	 * Proced to translate the template txt of the query in sqlPart
	 * 
	 * @param input
	 * @return
	 * @throws Exception
	 */
	protected static Map<String, SqlMapper> parse(Map<String, SqlMapper> input)
			throws Exception {
		// parse simple string
		for (SqlMapper item : input.values()) {
			TemplateParser.parse(item);
		}

		// once parsed string, execute the macro
		for (SqlMapper item : input.values()) {
			TemplateParser2.parse(item);
		}

		return input;
	}

	public static Map<String, SqlMapper> load(Sources sources) throws Exception {
		return parse(loadFromDefinition(sources));
	}

}
